from django.db import transaction
from rest_framework import serializers
from goods.models import SKU
from .models import OrderInfo,OrderGoods
from django.utils import timezone
from decimal import Decimal
from django_redis import get_redis_connection
class OrderPlaceSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField(min_value=1,label="数量")
    class Meta:
        model = SKU
        fields = ("default_image_url","name","price","count","id")


class OrderCommitSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderInfo
        fields = ("address","pay_method","order_id")

        read_only_fields = ["order_id"] #序列化的时候,(也就是返回的时候用,反序列化的时候不用)

        #write_only, 反序列化的时候用, 序列化的时候不用
        extra_kwargs = {
            "address":{
                "write_only":True
            },
            "pay_method":{
                "write_only":True
            }
        }

    #1,重写create方法,去出redis数据,创建订单对象, 订单商品对象
    @transaction.atomic
    def create(self, validated_data):

        #1,获取user
        user = self.context["request"].user

        #2,创建订单编号(尽量保证唯一性)
        order_id = timezone.now().strftime("%Y%m%d%H%M%S") + "%06d"%user.id

        #3,获取地址
        address = validated_data["address"]

        #4,获取支付方式
        pay_method = validated_data["pay_method"]

        #5,订单状态
        if pay_method == OrderInfo.PAY_METHODS_ENUM["CASH"]:
            status = OrderInfo.ORDER_STATUS_ENUM["UNCOMMENT"]
        else:
            status = OrderInfo.ORDER_STATUS_ENUM["UNPAID"]

        #TODO 设置保存点
        sid = transaction.savepoint()

        #6,创建订单信息对象
        order = OrderInfo.objects.create(
            order_id = order_id,
            user = user,
            address = address,
            total_count = 0,
            total_amount = Decimal(0.0),
            freight = Decimal(10.0),
            pay_method = pay_method,
            status = status,
        )

        #7,获取redis中数据
        redis_conn = get_redis_connection("cart")
        cart_dict = redis_conn.hgetall("cart_%s"%user.id)
        cart_selected_list = redis_conn.smembers("cart_selected_%s"%user.id)

        #8,遍历创建订单商品对象
        for sku_id in cart_selected_list:
            while True:
                #8.1获取商品对象,数量
                sku = SKU.objects.get(id=sku_id)
                count = int(cart_dict[sku_id])

                #8.2判断库存量是否足够
                if count > sku.stock:
                    #TODO 回滚
                    transaction.savepoint_rollback(sid)
                    raise serializers.ValidationError("库存不足")

                #TODO 模拟并发下单
                # import time
                # time.sleep(5)

                #8.3减少库存,增加销量
                # sku.stock -= count
                # sku.sales += count
                # sku.save()

                # TODO 使用乐观锁,解决并发下单问题
                old_stock = sku.stock
                old_sales = sku.sales
                new_stock = old_stock - count
                new_sales = old_sales + count

                ret =  SKU.objects.filter(id=sku_id,stock=old_stock).update(stock=new_stock,sales=new_sales)

                if ret == 0:
                    # raise serializers.ValidationError("下单失败")
                    continue #继续查询一次库存

                #8.4累加商品数量和价格
                order.total_count += count
                order.total_amount += (sku.price * count)

                #8.5创建订单商品对象
                OrderGoods.objects.create(
                    order=order,
                    sku=sku,
                    count=count,
                    price=sku.price,
                )
                break #必须退出

        #9,保存,清除redis数据
        order.save()
        transaction.savepoint_commit(sid) #TODO 提交
        redis_conn.hdel("cart_%s"%user.id,*cart_selected_list)
        redis_conn.srem("cart_selected_%s"%user.id,*cart_selected_list)

        #10,返回响应
        return order


class GoodCommentSerializer(serializers.ModelSerializer):
    """获取商品评论序列化器"""
    class Meta:
        model = OrderGoods
        fields = '__all__'


class SkuSerializer(serializers.ModelSerializer):
    class Meta:
        model = SKU
        fields = ('name', 'default_image_url', 'id')


class SkuCommentSerializer(serializers.ModelSerializer):
    """评论序列化器"""
    sku = SkuSerializer(read_only=True)
    sku_id = serializers.IntegerField(write_only=True, label='创建评论的商品id')

    class Meta:
        model = OrderGoods
        fields = ('comment', 'score', 'is_anonymous', 'order', 'sku_id', 'sku', 'price')
        read_only_fields = ('price',)

    def create(self, validated_data):
        print(validated_data)

        # 获取参数
        order = validated_data.get("order")
        sku_id = validated_data.get("sku_id")
        comment = validated_data.get("comment")
        score = validated_data.get("score")
        is_anonymous = validated_data.get("is_anonymous")
        # sku = validated_data.get("sku")

        # 查询订单商品
        order_goods = OrderGoods.objects.filter(order=order, sku_id=sku_id)
        print(order_goods)

        if not order_goods:
            raise serializers.ValidationError("订单不存在")

        order_goods = order_goods.first()
        with transaction.atomic():
            # 创建一个保存点
            save_id = transaction.savepoint()

            try:
                # 修改订单商品评价信息
                order_goods.comment = comment
                order_goods.score = score
                order_goods.is_anonymous = is_anonymous
                order_goods.is_commented = True
                order_goods.save()

                # 修改订单状态
                skus = OrderGoods.objects.filter(order=order)
                order = OrderInfo.objects.get(order_id=order.order_id)
                flag = 1
                if skus:
                    for i in skus:
                        if i.is_commented == 0:
                            flag = i.is_commented
                if flag:
                    order.status = OrderInfo.ORDER_STATUS_ENUM["FINISHED"]
                    order.save()

                # 商品的评论数加一
                order_goods.sku.comments += 1
                order_goods.sku.save()
            except:
                # 回滚
                transaction.savepoint_rollback(save_id)
                raise serializers.ValidationError("修改错误")
            else:
                # 修改成，提交
                transaction.savepoint_commit(save_id)

            # 返回数据
            return order_goods

